package com.mmall.pay.provider.service;

import com.common.framework.constant.DeleteStatus;
import com.google.common.base.Preconditions;
import com.mmall.order.api.bo.OrderBO;
import com.mmall.order.api.service.OrderService;
import com.mmall.pay.api.bo.PayInfoBO;
import com.mmall.pay.api.constant.PayStatus;
import com.mmall.pay.api.dto.PayApplyDTO;
import com.mmall.pay.api.dto.PayCallbackDTO;
import com.mmall.pay.api.service.PayService;
import com.mmall.pay.provider.dao.PayApplyMapper;
import com.mmall.pay.provider.helper.PayHelper;
import com.mmall.pay.provider.model.PayApplyDO;
import com.mmall.user.api.constant.ConstantError;
import org.apache.dubbo.config.annotation.Reference;
import org.apache.dubbo.config.annotation.Service;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;
import javax.validation.constraints.NotNull;
import static com.common.framework.exception.BusinessException.businessException;

/**
 * @author hejianglong
 * @date 2019/10/28
 */
@Component
@Service(version = "1.0.0")
public class PayServiceImpl implements PayService {
    //----- 本地调用方法 -----
    @Autowired
    private PayApplyMapper payApplyMapper;

    //----- 远程调用方法 -----
    @Reference(version = "1.0.0")
    private OrderService orderService;

    @Override
    @Transactional
    public void payApply(PayApplyDTO payApplyDTO) {
        final long orderId = payApplyDTO.getOrderId();
        OrderBO orderBO = getAndCheckOrder(orderId);
        if (!payApplyDTO.getTotalAmount().equals(orderBO.getTotalAmount())) {
            throw businessException(ConstantError.PAY_ORDER_TOTAL_AMOUNT_ERROR);
        }
        PayStatus payStatus = PayHelper.payApply(payApplyDTO);
        if (PayStatus.FAILED == payStatus) {
            throw businessException("申请支付失败");
        }
        // 记录申请支付的信息
        PayApplyDO payApplyDO = new PayApplyDO();
        payApplyDO.setOrderId(orderId)
                .setAmount(orderBO.getTotalAmount())
                .setPayChannel(payApplyDO.getPayChannel())
                .setStatus(payStatus.getCode())
                .setUserId(payApplyDTO.getUserId())
                .setDeleted(DeleteStatus.ACTIVE);
        payApplyMapper.insert(payApplyDO);
    }

    @Override
    public PayInfoBO needPayInfo(@NotNull Long orderId) {
        OrderBO orderBO = getAndCheckOrder(orderId);

        PayInfoBO payInfoBO = new PayInfoBO();
        payInfoBO.setCreateTime(orderBO.getCreateTime())
            .setOrderId(orderId)
            .setOrderNumber(orderBO.getOrderNumber())
            .setTotalAmount(orderBO.getTotalAmount())
            .setRemark(orderBO.getRemark());
        return payInfoBO;
    }

    @Override
    public void payCallback(PayCallbackDTO payCallbackDTO) {
        PayApplyDO payApplyDO = payApplyMapper.selectByOrderId(payCallbackDTO.getOrderId(), PayStatus.WAIT.getCode());
        Preconditions.checkNotNull(payApplyDO, "没有找到等待支付的订单 orderId: ", payCallbackDTO.getOrderId());
        payApplyDO.setStatus(payCallbackDTO.getPayStatus().getCode())
                .setPayNumber(payCallbackDTO.getPayNumber());
        payApplyMapper.updateById(payApplyDO);
    }

    private OrderBO getAndCheckOrder(@NotNull Long orderId) {
        OrderBO orderBO = orderService.getOrder(orderId);
        if (orderBO == null) {
            throw businessException(ConstantError.ORDER_IS_NOT_FOUND);
        }
        return orderBO;
    }
}
